package com.sp.scmdb.webservice.serviceImpl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sp.scmdb.common.CommonParamter;
import com.sp.scmdb.dao.ConfLabelIOUploadDao;
import com.sp.scmdb.dao.His_LabelIODao;
import com.sp.scmdb.dao.LabelIODao;
import com.sp.scmdb.dao.RealDataDao;
import com.sp.scmdb.entity.ConfLabelIOUpload;
import com.sp.scmdb.entity.His_LabelIO;
import com.sp.scmdb.entity.LabelIO;
import com.sp.scmdb.entity.SuperLabelIO;
import com.sp.scmdb.spring.ApplicationContext;
import com.sp.scmdb.webservice.model.LabelIOModel;
import com.sp.scmdb.webservice.model.RealDataModel;
import com.sp.scmdb.webservice.model.ReturnResponse;
import com.sp.scmdb.webservice.service.UploadDataService;
import com.sp.scmdb.webservice.service.UploadLabelIOService;
import com.sp.scmdb.webservice.suport.CastorSerializer;

@Service("uploadLabelIOService")
public class UploadLabelIOServiceImpl implements UploadLabelIOService {
	private static Log log = LogFactory.getLog(UploadLabelIOServiceImpl.class);

	private ConfLabelIOUploadDao confDao;
	private LabelIODao labelIODao;
	private His_LabelIODao hisLabelIODao;
	private RealDataDao realDataDao;
	public static final int EACH_ACCESS_NUMBER = 100; // 每次从数据库取的记录数量
	public static String MESSAGE_LABELIO_UPLOAD = "";

	/**
	 * 获取上传配置信息
	 */
	public ConfLabelIOUpload getUsedConfLabelIOUpload() {
		List<ConfLabelIOUpload> list = confDao
				.queryHql("from ConfLabelIOUpload where isUsed = 1");
		if (CollectionUtils.isNotEmpty(list)) {
			return list.get(0);
		}
		return null;
	}

	/**
	 * 停止轨迹数据上传
	 */
	@Transactional
	public String stopUploadLabelIO() {
		// 修改上传配置信息中的上传状态为“停止上传”
		try {
			ConfLabelIOUpload conf = this.getUsedConfLabelIOUpload();
			conf.setUploadStatus(0);
			confDao.update(conf);
		} catch (Exception e) {
			log.error("uploadLabelIO failed! reason:" + e.getMessage());
		}

		return "1";
	}

	/**
	 * 开始轨迹数据上传
	 */
	@SuppressWarnings("unchecked")
	@Transactional
	public String uploadLabelIO(String autoUploadTime) {
		try {
			// 修改上传配置信息中的上传状态为“正常上传”
			ConfLabelIOUpload conf = this.getUsedConfLabelIOUpload();
			// 如果是系统第一次连接数据平台进行数据上传（conf中的最后一次上传ID为空）
			if (conf.getLastUploadID() == null) {
				// 默认获取当前时间的一条数据ID最为开始
				List list = labelIODao
						.queryHql("select max(inTime) from LabelIO where inTime < '"
								+ (new DateTime()
										.toString("yyyy-MM-dd HH:mm:ss") + "'"));
				if (CollectionUtils.isNotEmpty(list)) {
					DateTime inTime = (DateTime) list.get(0);
					List<LabelIO> listLabelIO = labelIODao
							.queryHql("from LabelIO where inTime='"
									+ inTime
											.toString("yyyy-MM-dd HH:mm:ss.SSS")
									+ "'");
					if (CollectionUtils.isNotEmpty(listLabelIO)) {
						conf.setLastInTime(listLabelIO.get(0).getInTime());
						conf.setLastUploadID(listLabelIO.get(0).getId());
					}
				}
			}
			conf.setUploadStatus(1);
			conf.setAutoUploadTime(Integer.parseInt(autoUploadTime));
			if (null == conf.getLastInTime()) {
				conf.setLastInTime(new DateTime());
			}
			if (null == conf.getLastUploadID()) {
				conf.setLastUploadID(0);
			}
			confDao.update(conf);

		} catch (Exception e) {
			log.error("uploadLabelIO failed! reason:" + e.getMessage());
			return "10";
		}

		return "";
	}

	// 开启轨迹数据上传线程
	public String startThread() {
		UploadLabelIOThread thread = new UploadLabelIOThread();
		new Thread(thread).start();

		return "";
	}

	private class UploadLabelIOThread implements Runnable {
		@Override
		public void run() {

			// 此处放置需要自动执行的代码
			ConfLabelIOUpload conf = getUsedConfLabelIOUpload();
			if (conf != null) {
				String result = "";
				try {
					List<His_LabelIO> hisList = null;
					List<LabelIO> list = null;
					List<SuperLabelIO> superList = null;
					SuperLabelIO bean = null;
					LabelIOModel model = null;
					RealDataModel realDataModel = null;
					String str = "";
					CastorSerializer serializerTool = null;
					ByteArrayOutputStream byteOutputStream = null;
					UploadDataService upload = null;
					ReturnResponse response = null;
					while (true) {
						// 过n秒之后重新执行
						Thread.sleep(conf.getAutoUploadTime() * 1000);

						// 重新取配置信息
						conf = getUsedConfLabelIOUpload();

						// 检测配置信息中的上传状态，如果是1（1表示正常上传），则上传数据
						if (1 == conf.getUploadStatus()) {
							try {
								// 1、从数据库中取出n条记录
								Integer id = conf.getLastUploadID();
								DateTime inTime = conf.getLastInTime();
								hisList = getHisLabelIOList(
										inTime,
										UploadLabelIOServiceImpl.EACH_ACCESS_NUMBER);
								list = getLabelIOList(
										id,
										UploadLabelIOServiceImpl.EACH_ACCESS_NUMBER);
								superList = new ArrayList<SuperLabelIO>();
								if (hisList != null) {
									for (His_LabelIO entity : hisList) {
										bean = new SuperLabelIO();
										bean.setId(entity.getId());
										bean.setEmpID(entity.getEmpID());
										bean.setLabelID(entity.getLabelID());
										bean.setLrmID(entity.getLrmID());
										bean.setInTime(entity.getInTime());
										bean.setOutTime(entity.getOutTime());

										superList.add(bean);
									}
								}
								if (list != null) {
									for (LabelIO entity : list) {
										bean = new SuperLabelIO();
										bean.setId(entity.getId());
										bean.setEmpID(entity.getEmpID());
										bean.setLabelID(entity.getLabelID());
										bean.setLrmID(entity.getLrmID());
										bean.setInTime(entity.getInTime());
										bean.setOutTime(entity.getOutTime());

										superList.add(bean);
										id = entity.getId();
										inTime = entity.getInTime();
									}
								}

								// 2、将这些记录上传上去
								model = new LabelIOModel();
								model.setListSuperLabelIO(superList);

								model.setUserId(CommonParamter.userID);
								model.setPassword(CommonParamter.password);

								serializerTool = new CastorSerializer();
								byteOutputStream = new ByteArrayOutputStream();
								serializerTool
										.addMappingLocation("com/sp/scmdb/webservice/mapping/mapping.xml");
								serializerTool.marshal(model, byteOutputStream,
										"UTF-8");
								str = new String(byteOutputStream.toByteArray());

								upload = (UploadDataService) ApplicationContext
										.getBean("uploadService");
								result = upload.uploadTrack(str);

								// 获取返回值
								response = (ReturnResponse) serializerTool
										.unmarshal(new ByteArrayInputStream(
												result.getBytes()), "GB2312");

								// 3、如果上传成功，记录最后一条数据的ID；如果失败，则不做处理，等待下一次继续执行
								if ("1".equals(response.getReID())) {
									// 上传成功，记录最后一条数据ID
									conf.setLastUploadID(id);
									conf.setLastInTime(inTime);
									conf.setLastUploadTime(new DateTime());

									confDao.update(conf);
								}
								MESSAGE_LABELIO_UPLOAD = "轨迹："
										+ response.getDescription();

								// 4、上传实时数据
								realDataModel = new RealDataModel();
								realDataModel
										.setListRealData(realDataDao
												.queryHql("from RealData where employee.duty.dutyLevelId < 4"));

								realDataModel.setUserId(CommonParamter.userID);
								realDataModel
										.setPassword(CommonParamter.password);

								serializerTool = new CastorSerializer();
								byteOutputStream = new ByteArrayOutputStream();
								serializerTool
										.addMappingLocation("com/sp/scmdb/webservice/mapping/mapping.xml");
								serializerTool.marshal(realDataModel,
										byteOutputStream, "UTF-8");
								str = new String(byteOutputStream.toByteArray());

								upload = (UploadDataService) ApplicationContext
										.getBean("uploadService");
								result = upload.uploadRealData(str);

								// 获取返回值
								response = (ReturnResponse) serializerTool
										.unmarshal(new ByteArrayInputStream(
												result.getBytes()), "GB2312");
								MESSAGE_LABELIO_UPLOAD = MESSAGE_LABELIO_UPLOAD
										+ "  实时数据：" + response.getDescription();

							} catch (javax.xml.ws.WebServiceException e) {
								log.error("uploadLabelIOThread failed! reason:"
										+ e.getMessage());
							} catch (Exception e) {
								log.error("uploadLabelIOThread failed! reason:"
										+ e.getMessage());
							}
						}
					}

				} catch (javax.xml.ws.WebServiceException e) {
					// 4、如果抛出异常（连接超时等），则跳出循环，结束线程；同时修改上传状态，返回失败信息
					conf.setUploadStatus(0);
					confDao.update(conf);
					log.error("uploadLabelIO failed! reason:" + e.getMessage());
					if ("Could not send Message.".equals(e.getMessage())) {
						result = "无法连接到服务器！";
					}
				} catch (Exception e) {
					// 4、如果抛出异常（连接超时等），则跳出循环，结束线程；同时修改上传状态，返回失败信息
					conf.setUploadStatus(0);
					confDao.update(conf);
					log.error("uploadLabelIO failed! reason:" + e.getMessage());
					result = e.getMessage();
				}
			}
		}
	}

	@SuppressWarnings("unchecked")
	public List<His_LabelIO> getHisLabelIOList(DateTime inTime, int length) {
		List list = hisLabelIODao
				.queryHql("select min(id) from His_LabelIO where inTime>='"
						+ inTime.toString("yyyy-MM-dd HH:mm:ss.SSS") + "'");
		Iterator iter = list.iterator();
		if (iter.hasNext()) {
			Object ids = iter.next();
			if (null != ids) {
				int id = (Integer) list.get(0);
				if (id > 0) {
					List<His_LabelIO> hisList = hisLabelIODao
							.queryHql("from His_LabelIO " + "where id>" + id
									+ " and id <" + (id + length)
									+ " and employee.duty.dutyLevelId < 4"
									+ " order by inTime asc ");
					return hisList;
				} else {
					return null;
				}
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	public List<LabelIO> getLabelIOList(int startID, int length) {
		List<LabelIO> list = labelIODao.queryHql("from LabelIO where id>"
				+ startID + " and id <" + (startID + length)
				+ " and employee.duty.dutyLevelId < 4" + " order by id asc ");

		return list;
	}

	/**
	 * 更新上传配置信息
	 * 
	 * @param conf
	 */
	public void updateConfLabelIOUpload(ConfLabelIOUpload conf) {
		confDao.update(conf);
	}

	@Autowired
	public void setConfDao(ConfLabelIOUploadDao confDao) {
		this.confDao = confDao;
	}

	@Autowired
	public void setLabelIODao(LabelIODao labelIODao) {
		this.labelIODao = labelIODao;
	}

	@Autowired
	public void setHisLabelIODao(His_LabelIODao hisLabelIODao) {
		this.hisLabelIODao = hisLabelIODao;
	}

	@Autowired
	public void setRealDataDao(RealDataDao realDataDao) {
		this.realDataDao = realDataDao;
	}
}
